from view.endSrc.ObserverGenerator import ObserverGenerator
from view.endSrc.Dataset import Dataset
import numpy as np
import random
from random import choice
import sympy as sp


class EdgeObserverGenerator(ObserverGenerator):

    def _solve(self, nViewPoint, dim):
        if dim >= nViewPoint:
            return 2

        x = sp.Symbol('x', real=True, nonnegative=True)
        f = x**dim - (x-2)**dim - nViewPoint
        x = sp.solve(f)
        x = np.ceil(max(x))
        if x < 1:
            return 2
        return x

    def getViewPointList(self, dataset: Dataset, nViewPoints, p2pFun, n2nFun):
        minima = np.min(dataset, axis=0)
        minima = minima - abs(minima) * 0.01
        maxima = np.max(dataset, axis=0)
        maxima = maxima + abs(maxima) * 0.01

        dim = dataset.getNumOfAttributes()
        k = self._solve(nViewPoints, dim)
        segment = np.linspace(0, 1, k)
        random.seed(5)
        segmentCollect = []
        while len(segmentCollect) < nViewPoints:
            segItem = []
            for j in range(dim):
                segItem.append(choice(segment))

            segItem[len(segmentCollect) % dim] = choice([0, 1])

            if segItem in segmentCollect:
                continue
            segmentCollect.append(segItem)

        vpList = []
        for i in range(nViewPoints):
            point = minima + (maxima-minima)*segmentCollect[i]
            vpList.append(np.asarray(point))

        # import matplotlib.pyplot as plt
        # plt.scatter(dataset[:, 0], dataset[:, 1], marker='+')
        # for point in vpList:
        #     plt.scatter(point[0], point[1], marker='D', s=150)
        # plt.show()
        return vpList
